package ke24.ga;

import java.util.HashMap;

import org.jgap.*;
import org.jgap.impl.*;

/**
 * Fitness function for load distribution problem
 *
 * @author tan
 */
public class LoadDistributionFitnessFunction
    extends FitnessFunction {


  
  private Package[] pkgs;
  private double average; 
  private HashMap<Integer,Double> weightMap;
  
  public LoadDistributionFitnessFunction(Package[] pkgs) {
      this.pkgs = pkgs;
      this.average = getAverage();
      this.weightMap = createPackageMap();
  }
  
  public  HashMap<Integer,Double>  getWeightMap(){
      return this.weightMap;
  }
  
  private HashMap<Integer, Double> createPackageMap() {
    HashMap<Integer,Double> map = new HashMap<Integer, Double>();
    for (Package p : pkgs) {
        map.put(new Integer(p.getId()), new Double(p.getWeight()));
    }
    return map;
}

private double getAverage() {
      double avg = 0;
      for (Package p : this.pkgs) {          
          avg +=p.getWeight();
      }
      
      return avg / this.pkgs.length;

}



/**
   * Calculates the difference in weight between the 16 groups of packages. The
   * lower the different the better the solution.
   *
   * @param a_subject the Chromosome to be evaluated
   * @return fitness of our problem (smaller is better here)
   *
   * @author tan
   */
  public double evaluate(IChromosome a_subject) {
    double squaredDiff = 0.0d;
    
    
        
    //System.out.println(" FITNESS FUNCTION - Average = " + this.average);
    
    for (int i = 0; i < 16; i++) {
      double groupWeight = 0.0d;
      for (int j = 0; j < 4; j++) {
        IntegerGene ventIndex = (IntegerGene) a_subject.getGene( (i * 4 + j));        
        //groupWeight += pkgs[ventIndex.intValue()].getWeight();
        groupWeight += this.weightMap.get((Integer)ventIndex.getAllele());
      }
      groupWeight /= 4;
      squaredDiff += (groupWeight - this.average) * (groupWeight - this.average);
    }
    //System.out.println(" FITNESS FUNCTION - STDEV = " + squaredDiff);

    return squaredDiff;
  }
}
